/** Copyright 2014, Ross Mahony. Some rights reserved. See COPYING. */
package controllers

import play.api._
import play.api.mvc._
import play.api.data._
import play.api.data.format.Formats._ 
import play.api.data.Forms._
import play.api.db.slick._
import play.api.db.slick.{ Session => SlickSession }
import play.api.libs.json._

import views._
import models._

/** [[play.api.mvc.Controller]] for the tips forum view. */
object Tips extends Controller {

  /** Retrieve tips and comments. */
  def getTips()(implicit s: SlickSession) = {
    val tips = TipDAO.listWithCustomer
    Logger.debug(f"Retrieved tips, size:[${tips.size}%d")
    tips
  }

  /** Retrieve tips and comments. */
  def getTipComments()(implicit s: SlickSession) = {
    val comments = TipDAO.listCommentsWithCustomer
    Logger.debug(f"Retrieved tip comments, size:[${comments.size}%d")
    comments
  }

  /** Retrieve tip likes. */
  def getTipLikes()(implicit s: SlickSession) = {
    val tipLikes = TipDAO.listLikes
    Logger.debug(f"Retrieved tip likes, size:[${tipLikes.size}%d]")
    tipLikes
  }

  val tipLikeForm = Form(
    mapping(
      "tipId" -> longNumber,
      "customerId" -> longNumber
    ) (TipLike.apply) (TipLike.unapply)
  )

 /** Action to like a tip. */
  def like = DBAction { implicit rs =>
    Logger.debug("in like tip")
    val tipLike = tipLikeForm.bindFromRequest.get // will throw error if cant bind to form but unlikely with this form
    Logger.debug(s"tip id:${tipLike.tipId} and customer id:${tipLike.customerId}")
    
    val allLikes: Map[Long, List[Long]] = TipDAO.listLikes
    if (allLikes.contains(tipLike.tipId) && allLikes(tipLike.tipId).contains(tipLike.customerId)) {
      Logger.debug("Customer has already liked this tip")  
    } else {
      TipDAO.insertLike(tipLike)  
    }

    Ok(s"${TipDAO.countLikes(tipLike.tipId)} likes")
  }

  val tipAddForm = Form(
    mapping(
      "tipId" -> optional(longNumber),
      "summary" -> nonEmptyText,
      "detail" -> nonEmptyText,
      "customerId" -> longNumber
    ) (Tip.apply) (Tip.unapply)
  )

  /** Action to add a tip. */
  def add = DBAction { implicit rs =>
    Logger.debug("in add tip")

    val tipAdd = tipAddForm.bindFromRequest.get
    Logger.debug("tipAdd, customer id:" + tipAdd.customerId)
    TipDAO.insert(tipAdd)

    Redirect(routes.Roadmaps.index(Some(tipAdd.customerId))).flashing(
      "success" -> "Tip added")
    
  }

  val deleteForm = Form(
    single(
      "tipId" -> longNumber
    )
  )

  /** Action to delete a tip. */
  def delete = DBAction { implicit rs =>
    Logger.debug("in delete tip")

    val tipId = deleteForm.bindFromRequest.get

    TipDAO.deleteAllComments(tipId)
    TipDAO.deleteAllLikes(tipId)
    TipDAO.delete(tipId)

    val json: JsValue = Json.obj(
      "tipId" -> JsNumber(tipId)
    )

    Ok(json)
  }    

  val tipCommentForm = Form(
    mapping(
      "id" -> optional(longNumber),
      "tipId" -> longNumber,
      "customerId" -> longNumber,
      "comment" -> nonEmptyText
    ) (TipComment.apply) (TipComment.unapply)
  )

  /** Action to add a comment. */
  def comment = DBAction { implicit rs =>
    Logger.debug("in comment")
    val tipComment = tipCommentForm.bindFromRequest.get
    Logger.debug(s"tip id:${tipComment.tipId} and customer id:${tipComment.customerId} comment:${tipComment.comment}")

    val commentId = TipDAO.insertComment(tipComment)

    val customer = CustomerDAO.findById(tipComment.customerId).get

    val json: JsValue = Json.obj(
      "commentId" -> JsNumber(commentId),
      "tipId" -> JsNumber(tipComment.tipId),
      "comment" -> JsString(tipComment.comment),
      "name" -> JsString(customer.name),
      "lastName" -> JsString(customer.lastName)
    )

    Ok(json)
  }       

  val deleteCommentForm = Form(
    single(
      "commentId" -> longNumber
    )
  )

  /** Action to delete a comment. */
  def deleteComment = DBAction { implicit rs =>
    Logger.debug("in delete tip comment")

    val commentId = deleteCommentForm.bindFromRequest.get

    TipDAO.deleteComment(commentId)

    val json: JsValue = Json.obj(
      "commentId" -> JsNumber(commentId)
    )

    Ok(json)
  }    
}